<script setup lang='ts'>
import { AIDrawMenuImageInfo } from '@/models/aidraw';
import { appRef } from '@/models/app.ref';
import { AssetInfo } from '@/models/asset';
import { mediaService } from '@/services/media.service';
import { hope } from '@/tools/hope/@types/hope';
import { getUuid } from '@/utils/common.methods';
import { FileItem } from '@arco-design/web-vue';
import { onMounted, ref, watch } from 'vue';
import { workService } from "@/services/work.service.ts";

const props = defineProps<{ info: AIDrawMenuImageInfo, isDraw: boolean }>();
const emits = defineEmits(['draw'])
const PromptPlaceholder = '如：1只穿着机械化装甲套装的布娃娃猫，透明头盔，Fluffy，使用爆炸火箭喷气背包飞行，太空舱中，爆炸背后是火花冒烟的火箭引擎，最佳画质，高分辨率，清晰对焦，高细节，电影阴影，侧光效果，动态模糊，电影灯光'
const NegativePromptPlaceholder = '如：水印，带有水印的，文本，JPEG图像瑕疵，低质量，不安全内容，裸体，裸露，色情，最差质量，低质量，裁剪，超出画面，绘制不精细，解剖错误，额外的四肢，缺失肢体，漂浮的肢体，变异的手和手指，脱节的肢体，额外的腿，融合的手指，过多的手指，长颈鸟，变异，变异的，丑陋，恶心，截肢，模糊，签名'

const ratios = [
  { name: '1:1', alias: '方', value: 1 / 1 },
  { name: '4:3', alias: '宽', value: 4 / 3 },
  { name: '3:4', alias: '高', value: 3 / 4 },
  { name: '16:9', alias: '16:9', value: 16 / 9 },
  { name: '9:16', alias: '9:16', value: 9 / 16 },
]

watch(() => [props.info?.uid], () => {
  init();
})

onMounted(() => {
  init();
})

async function init(): Promise<void> {
  if (!props.info?.picture_weight) props.info.picture_weight = 50;
  if (!props.info?.ratio) props.info.ratio = ratios[0].alias;
  if (props.info?.original) original.value = props.info.original;
}

const original = ref({} as AssetInfo)
const onChange = (_, currentFile: FileItem) => {
  currentFile.uid = getUuid();
  hope.upload({
    files: [currentFile.file],
    success: (res) => {
      original.value = res[0]
    }
  })
};

function onDraw(): void {
  const { forward, exclude, step, width, height, picture_weight, ratio, model } = props.info;
  emits('draw', {
    prompt: forward,
    negative_prompt: exclude,
    width,
    height,
    ratio,
    step,
    picture_weight: picture_weight,
    original: original.value,
    model_name: model
  });
}

const isInspiration = ref(false);

function getRandomImage(): void {
  isInspiration.value = true;
  mediaService.getOne().then((res) => {
    isInspiration.value = false;
    const { prompt, negativePrompt, blob } = res;
    props.info.forward = prompt;
    props.info.exclude = negativePrompt;
    // original.value = { uid: getUuid(), file: blobToFile(blob), url: URL.createObjectURL(blob) }
  })
}

function onChangeRatio(ratio: { name: string, alias: string, value: number }): void {
  props.info.ratio = ratio.alias;
  if (props.info.width) {
    props.info.height = props.info.width / ratio.value;
  } else if (props.info.height) {
    props.info.width = props.info.height * ratio.value;
  }
  let isHeight = props.info.height > maxWidth || props.info.height < minWidth ? true : false
  autoWidthHeight(isHeight);
}

const maxWidth = 1024;
const minWidth = 512;

function autoWidthHeight(isHeight: boolean = false): void {
  let ratio = ratios.find(val => val.alias === props.info.ratio)?.value;
  if (isHeight) {
    if (props.info.height > maxWidth) {
      ratio = props.info.height / maxWidth;
      props.info.height = maxWidth
    } else if (props.info.height < minWidth) {
      ratio = props.info.height / minWidth;
      props.info.height = minWidth
    }
    props.info.width = props.info.height / ratio;
  } else {
    if (props.info.width > maxWidth) {
      ratio = props.info.width / maxWidth;
      props.info.width = maxWidth
    } else if (props.info.width < minWidth) {
      ratio = props.info.width / minWidth;
      props.info.width = minWidth
    }
    props.info.height = props.info.width / ratio;
  }
  props.info.width = Math.floor(props.info.width)
  props.info.height = Math.floor(props.info.height)
}

const isOptimize = ref(false);
const optimizeKey = getUuid();
function optimizePrompt() {
  if (props.isDraw || !props.info.forward) return;
  let chunk = '';
  isOptimize.value = true
  workService.optimize(optimizeKey, props.info.forward, data => {
    chunk += data
    props.info.forward = chunk
  }, () => {
    props.info.forward = chunk
    isOptimize.value = false
  })
}

</script>
<template>
  <div class="setting flex-c">
    <div class="group">
      <div class="cell">
        <div class="title">提示词 Prompt</div>
        <div class="value">
          <a-textarea class="textarea" style="padding-bottom: 30px;" v-model="info.forward" :placeholder="PromptPlaceholder"
            :auto-size="{ minRows: 4, maxRows: 8 }">
          </a-textarea>
          <div class="optimize flex" :style="{ opacity: (isDraw || !info.forward || isOptimize) ? .7 : 1 }"
            @click="optimizePrompt">
            <img src="@/assets/icons/chat/optimize.png" :class="{ 'loading': isOptimize }">
            {{ isOptimize ? "优化中" : "优化" }}
          </div>
        </div>
      </div>
      <div class="cell">
        <div class="title">不希望出现的内容 Negative Prompt</div>
        <div class="value">
          <a-textarea class="textarea" v-model="info.exclude" :placeholder="NegativePromptPlaceholder"
            :auto-size="{ minRows: 2, maxRows: 4 }" />
        </div>
      </div>
      <div class="cell">
        <div class="title">
          参考图
          <icon-delete v-if="original?.id" @click="original = <AssetInfo>{}" />
        </div>
        <div class="value">
          <a-upload action="/" :show-file-list="false" @change="onChange">
            <template #upload-button>
              <div class="arco-upload-list-picture custom-upload-avatar" v-if="original?.id">
                <img :src="original.url" />
                <div class="arco-upload-list-picture-mask">
                  <IconEdit />
                </div>
              </div>
              <div class="arco-upload-picture-card" v-else>
                <div class="arco-upload-picture-card-text">
                  <IconPlus />
                </div>
              </div>
            </template>
          </a-upload>
        </div>
      </div>
      <div class="cell">
        <div class="title">
          参考图相关性
          <a-tooltip content="生成的图片参考图的相关程度，越高接近参考图">
            <icon-question-circle />
          </a-tooltip>
        </div>
        <div class="value">
          <a-slider :default-value="50" v-model:model-value="info.picture_weight" />
        </div>
      </div>
      <div class="cell">
        <div class="title">图片比例</div>
        <a-space class="value">
          <a-button :value="ratio.value" v-for="ratio in ratios"
            :type="info.ratio === ratio.alias ? 'outline' : 'secondary'" @click="onChangeRatio(ratio)">
            {{ ratio.name }}
          </a-button>
        </a-space>
      </div>
      <div class="cell">
        <div class="title">模型</div>
        <div class="value">
          <a-select class="send" v-model="info.model" placeholder="请选择模型">
            <a-option v-for="item in appRef.aidraw.models" :value="item.name" :label="item.alias || item.name"></a-option>
          </a-select>
        </div>
      </div>
      <div class="cell">
        <div class="title">图片大小</div>
        <a-space class="value">
          <a-input-number v-model="info.width" placeholder="单位：px" :min="minWidth" :max="maxWidth"
            @change="autoWidthHeight()">
            <template #prefix> 宽</template>
          </a-input-number>
          <a-input-number v-model="info.height" placeholder="单位：px" :min="minWidth" :max="maxWidth"
            @change="autoWidthHeight(true)">
            <template #prefix> 高</template>
          </a-input-number>
        </a-space>
      </div>
      <div class="cell">
        <div class="title">
          推理步数
          <a-tooltip content="模型推理的步数，越大质量越高，耗时也越长">
            <icon-question-circle />
          </a-tooltip>
        </div>
        <div class="value">
          <a-input-number v-model="info.step" placeholder="不填则为随机" class="input-demo" :min="1" :max="50" />
        </div>
      </div>
    </div>
    <div class="bottom grid2">
      <a-button long @click="getRandomImage" :loading="isInspiration">
        <template #icon>
          <icon-bulb />
        </template>
        灵感
      </a-button>
      <a-button long type="primary" @click="onDraw" :loading="isDraw">
        <template #icon>
          <icon-highlight />
        </template>
        绘制
      </a-button>
    </div>
  </div>
</template>
<style lang='scss' scoped>
.setting {
  width: 400px;
  height: 100%;
  min-height: 100%;
  padding: 20px 0;
  border: 1px solid var(--color-neutral-4);
  margin-right: 10px;
  overflow: hidden;

  .group {
    width: 100%;
    flex: 1;
    padding: 0 20px;
    overflow-y: auto;

    .cell {
      margin-bottom: 20px;

      .title {
        font-size: 14px;
        color: var(--color-neutral-8);
        margin-bottom: 10px;
      }

      .value {
        position: relative;

        .tag {
          width: 70px;
          justify-content: center;
        }

        .optimize {
          cursor: pointer;
          font-size: 12px;
          position: absolute;
          bottom: 10px;
          right: 20px;

          img {
            width: 20px;
            height: 20px;
            margin-right: 4px;
          }
        }
      }
    }
  }

  .bottom {
    width: 100%;
    margin-top: 20px;
    padding: 0 20px;
  }

  @media screen and (max-width: 1200px) {
    width: 100%;
    flex: none;
    margin: 0;
    height: auto;
    margin-bottom: 20px;
  }
}
</style>